<template>
    <div ref="echartDom"></div>
  </template>
  
  <script setup>
  import {ref, defineProps, onMounted, onUnmounted, inject, shallowRef, defineExpose} from 'vue'
  import {pxToRem} from "@/utils/index";
  
  const props = defineProps({
    graphData: {
      type: Object,
      default: () => {
      }
    }
  });
  
  const echartDom = ref(null);
  const myChart = shallowRef(null);
  const echarts = inject('echarts');
  
  const initEchart = () => {
    if (echartDom.value) {
      myChart.value = echarts.init(echartDom.value);
      let option = {
        legend: {
          right: 0,
          icon: 'rect',
          itemWidth: pxToRem(10),
          itemHeight: pxToRem(10),
          textStyle: {
            color: 'white',
            fontSize: pxToRem(12)
          },
          data: [
            {
              name: '开发商',
              itemStyle: {
                color: '#E65992'
              }
            },
            {
              name: '户型',
              itemStyle: {
                color: '#0E5FFF'
              }
            },
            {
              name: '购房人年龄',
              itemStyle: {
                color: '#01C4D2'
              }
            }
          ]
        },
        xAxis: {
          show: false
        },
        yAxis: {
          show: false
        },
        series: [
          {
            type: "graph",
            left: '0',
            right: '0',
            bottom: '0',
            top: '0',
            zoom: .7,
            // 力引导布局相关的配置项，力引导布局是模拟弹簧电荷模型在每两个节点之间添加一个斥力，每条边的两个节点之间添加一个引力，每次迭代节点会在各个斥力和引力的作用下移动位置，多次迭代后节点会静止在一个受力平衡的位置，达到整个模型的能量最小化。
            force: {
              initLayout: 'circular', // 初始布局
              repulsion: pxToRem(1000),       // 节点之间的推荐力
              edgeLength: [pxToRem(150), pxToRem(500)],        // 边的长度，即节点之间的距离
              gravity: 0.1,          // 重力，影响节点下落
              // 是否在布局计算后调整布局，使节点不超出边界
              preventOverlap: true,
              // 布局的容忍系数，0 表示不允许节点与节点之间有任何重叠，1 表示完全允许重叠
              tolerance: 1,
              // 布局的容忍系数，0 表示不允许边与边之间有任何相交，1 表示完全允许边相交
              edgeTolerance: 1
            },
            scaleLimit: {
              min: 0.4,
              max: 2
            },
            // 设置图表的布局中心点，使图表居中
            layoutCenter: ['50%', '50%'],
            // 设置节点之间的距离，防止节点相互之间相互覆盖
            preventOverlap: true,
            roam: true,
            layout: "force",
            symbol: 'circle',
            // 关系对象上的标签
            label: {
              normal: {
                // 是否显示标签
                show: true,
                // 标签位置:'top''left''right''bottom''inside''insideLeft''insideRight''insideTop''insideBottom''insideTopLeft''insideBottomLeft''insideTopRight''insideBottomRight'
                position: "inside",
                // 文本样式
                textStyle: {
                  fontSize: pxToRem(10),
                  color: 'white'
                }
              }
            },
            lineStyle: {
              color: "white"
            },
            // 连接两个关系对象的线上的标签
            edgeLabel: {
              normal: {
                show: false,
                textStyle: {
                  fontSize: pxToRem(10),
                  color: 'white',
                },
                // 标签内容
                formatter: function (param) {
                  return param.data.category;
                }
              }
            },
            // 节点分类的类目，可选。如果节点有分类的话可以通过 data[i].category 指定每个节点的类目，类目的样式会被应用到节点样式上。图例也可以基于categories名字展现和筛选。
            categories: [
              {
                // 类目名称，用于和 legend 对应以及格式化 tooltip 的内容。
                name: "户型"
              },
              {
                name: "开发商"
              },
              {
                name: "购房人年龄"
              }
            ],
            symbolSize: [pxToRem(60), pxToRem(60)], // 关系图节点标记的大小，可以设置成诸如 10 这样单一的数字，也可以用数组分开表示宽和高，例如 [20, 10] 表示标记宽为20，高为10。
            draggable: true, // 节点是否可拖拽，只在使用力引导布局的时候有用。
            cursor: 'pointer',
            data: props?.graphData?.seriesData?.data,
            emphasis: {
              edgeLabel: {
                show: true // 在 hover 时显示边的标签
              }
            },
            // 节点间的关系数据
            links: props?.graphData?.seriesData?.links
          }]
      }
      option && myChart.value.setOption(option, true);
    }
  }
  
  const updateChart = () => {
    if (myChart.value) {
      myChart.value.dispose(); // 销毁旧图表实例
    }
    initEchart();
  };
  
  defineExpose({
    updateChart
  })
  
  onMounted(() => {
    initEchart();
    window.addEventListener("resize", updateChart);
  })
  
  onUnmounted(() => {
    window.removeEventListener("resize", updateChart);
  })
  </script>
  
  <style scoped lang="less">
  .h279 {
    height: 200px;
  }
  </style>